<template>
  <div class="tableRow">
    <el-row class="select-list" v-permission="'monitor:job:query'">
      <el-form :inline="true" ref="selectForm" :model="selectFormModel" label-position="right"
               label-width="80px" size="mini">
        <el-form-item label="任务名称" prop="jobName">
          <el-input v-model="selectFormModel.jobName" placeholder="任务名称" style="width: 200px" clearable
                    @keyup.enter.native="onSearch"/>
        </el-form-item>
        <el-form-item label="任务分组" prop="jobGroup">
          <el-select value="" v-model="selectFormModel.jobGroup" placeholder="任务分组"
                     @keyup.enter.native="onSearch">
            <el-option label="默认" value="DEFAULT"/>
            <el-option label="系统" value="SYSTEM"/>
          </el-select>
        </el-form-item>
        <el-form-item label="任务状态" prop="status">
          <el-select value="" v-model="selectFormModel.status" placeholder="任务状态" style="width: 200px">
            <el-option label="正常" value="0"/>
            <el-option label="停止" value="1"/>
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="el-icon-search" size="mini" plain round @click="onSearch">搜索
          </el-button>
          <el-button type="warning" icon="el-icon-refresh" size="mini" plain round
                     @click="onRefreshSelectForm">重置
          </el-button>
        </el-form-item>
      </el-form>
    </el-row>
    <el-row class="toolbar">
      <el-button type="primary" icon="el-icon-plus" size="mini" plain @click="handleAdd"
                 v-permission="'monitor:job:add'">
        新增
      </el-button>
      <el-button type="info" icon="el-icon-edit" :disabled="dialog.isBatchEditDisabled" size="mini" plain
                 @click="handleEdit" v-permission="'monitor:job:edit'"> 编辑
      </el-button>
      <el-button type="danger" icon="el-icon-delete" :disabled="dialog.isBatchRemoveDisabled" size="mini" plain
                 @click="handleBatchDelete" v-permission="'monitor:job:remove'"> 删除
      </el-button>
      <el-button type="warning" icon="el-icon-download" size="mini" plain @click="handleExport"
                 v-permission="'monitor:job:export'"> 导出
      </el-button>

      <el-button type="success" icon="fa fa-list" size="mini" plain
                 @click="handleJobLogsInfo" v-permission="'monitor:job:log'"> 日志
      </el-button>
    </el-row>
    <data-table
      class="table"
      ref="dataTable"
      :api="getJobList"
      :options="options"
      :columns="columns"
      :operates="operates"
      :query="selectFormModel"
      @handle-selection-change="handleSelectionChange"
    />

    <el-dialog
      :title="dialog.title"
      :visible.sync="dialog.dialogFormVisible"
      :modal-append-to-body="false"
      :destroy-on-close="false"
      @close="closeDialog"
      width="600px">
      <el-form :model="jobModel" ref="jobForm" label-width="100px" :rules="jobFormRules" size="small">
        <el-form-item label="任务名称" prop="jobName">
          <el-input v-model="jobModel.jobName" placeholder="任务名称"/>
        </el-form-item>
        <el-form-item label="任务分组" prop="jobGroup">
          <el-select value="" v-model="jobModel.jobGroup" placeholder="任务分组">
            <el-option label="默认" value="DEFAULT"/>
            <el-option label="系统" value="SYSTEM"/>
          </el-select>
        </el-form-item>
        <el-form-item label="调用字符串" prop="invokeTarget">
          <el-input v-model="jobModel.invokeTarget" placeholder="调用字符串"/>
        </el-form-item>
        <el-form-item label="cron表达式" prop="cronExpression">
          <el-input v-model="jobModel.cronExpression" placeholder="cron表达式"/>
        </el-form-item>
        <el-form-item label="执行策略">
          <el-radio-group v-model="jobModel.misfirePolicy">
            <el-radio label="1">立即执行</el-radio>
            <el-radio label="2">执行一次</el-radio>
            <el-radio label="3">放弃执行</el-radio>
          </el-radio-group>
        </el-form-item>

        <el-form-item label="并发执行">
          <el-switch
            v-model="jobModel.concurrent"
            active-color="#13ce66"
            inactive-color="#ff4949"
            active-text="允许"
            inactive-text="禁止"
            active-value="0"
            inactive-value="1"/>
        </el-form-item>
        <el-form-item label="状态">
          <el-switch
            v-model="jobModel.status"
            active-color="#13ce66"
            inactive-color="#ff4949"
            active-text="正常"
            inactive-text="停止"
            active-value="0"
            inactive-value="1"/>
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input v-model="jobModel.remark" placeholder="备注" maxlength="100"/>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialog.dialogFormVisible=false" size="medium">取 消</el-button>
        <el-button type="primary" @click="submitForm" size="medium">确 定</el-button>
      </div>
    </el-dialog>

    <el-dialog :title="dialog.title" :visible.sync="dialog.logVisible " :modal-append-to-body="false"
               width="800px">
      <el-row class="item">
        <el-col :span="12">
          <el-row>
            <el-col :span="8">
              任务编号：
            </el-col>
            <el-col :span="16">
              <span> {{ dialog.row.id }}</span>
            </el-col>
          </el-row>
        </el-col>
        <el-col :span="12">
          <el-row>
            <el-col :span="8">
              任务分组：
            </el-col>
            <el-col :span="16">
              <span v-if="dialog.row.jobGroup==='DEFAULT'"> 默认 </span>
              <span v-else-if="dialog.row.jobGroup==='SYSTEM'"> 系统 </span>
            </el-col>
          </el-row>
        </el-col>
      </el-row>
      <el-row class="item">
        <el-col :span="12">
          <el-row>
            <el-col :span="8">
              任务名称：
            </el-col>
            <el-col :span="16">
              <span>{{ dialog.row.jobName }}</span>
            </el-col>
          </el-row>
        </el-col>
        <el-col :span="12">
          <el-row>
            <el-col :span="8">
              创建时间：
            </el-col>
            <el-col :span="16">
              <span> {{ dialog.row.createTime }}</span>
            </el-col>
          </el-row>
        </el-col>
      </el-row>
      <el-row class="item">
        <el-col :span="12">
          <el-row>
            <el-col :span="8">
              任务状态：
            </el-col>
            <el-col :span="16">
              <span v-if="dialog.row.status==='0'"> 正常 </span>
              <span v-else-if="dialog.row.status==='1'"> 停止 </span>
            </el-col>
          </el-row>
        </el-col>
        <el-col :span="12">
          <el-row>
            <el-col :span="8">
              下次执行时间：
            </el-col>
            <el-col :span="16">
              <span> {{ dialog.row.nextValidTime }}</span>
            </el-col>
          </el-row>
        </el-col>
      </el-row>

      <el-row class="item">
        <el-col :span="4">
          cron表达式：
        </el-col>
        <el-col :span="20">
          <span> {{ dialog.row.cronExpression }}</span>
        </el-col>
      </el-row>
      <el-row class="item">
        <el-col :span="4">
          调用字符串：
        </el-col>
        <el-col :span="20">
          <span> {{ dialog.row.invokeTarget }}</span>
        </el-col>
      </el-row>

      <el-row class="item">
        <el-col :span="12">
          <el-row>
            <el-col :span="8">
              是否并发：
            </el-col>
            <el-col :span="16">
              <span v-if="dialog.row.concurrent==='0'"> 允许 </span>
              <span v-else-if="dialog.row.concurrent==='1'"> 禁止 </span>
            </el-col>
          </el-row>
        </el-col>
        <el-col :span="12">
          <el-row>
            <el-col :span="8">
              执行策略：
            </el-col>
            <el-col :span="16">
              <span v-if="dialog.row.misfirePolicy==='0'"> 默认 </span>
              <span v-else-if="dialog.row.misfirePolicy==='1'"> 立即执行 </span>
              <span v-else-if="dialog.row.misfirePolicy==='2'"> 执行一次 </span>
              <span v-else-if="dialog.row.misfirePolicy==='3'"> 放弃执行 </span>
            </el-col>
          </el-row>
        </el-col>

      </el-row>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialog.logVisible = false" size="medium">取 消</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script lang="ts">
import {Component, Ref, Vue} from 'vue-property-decorator';
import {addJob, checkCronExpressionIsValid, exportJob, getJobList, removeJob, runJob, updateJob} from '@/api/job';
import DataTable from '@/components/DataTable/DataTable.vue';
import {validateForm} from '@/utils';

@Component({
  components: {
    DataTable
  }
})
export default class Job extends Vue {
  @Ref('dataTable') private dataTable: any;
  @Ref('selectForm') private selectForm: any;
  @Ref('jobForm') private jobForm: any;
  private getJobList: any = getJobList;


  selectFormModel: any = {
    jobName: '',
    jobGroup: '',
    status: '',
  };

  dialog: any = {
    dialogFormVisible: false,
    title: '对话框',
    isEdit: false,
    isBatchEditDisabled: true,
    isBatchRemoveDisabled: true,
    formData: [],
    logVisible: false,
    row: {}
  };

  jobModel: any = {
    jobName: '',
    jobGroup: 'DEFAULT',
    invokeTarget: '',
    cronExpression: '',
    misfirePolicy: '1',
    concurrent: '1',
    status: '1',
    remark: ''
  };

  jobFormRules: any = {
    jobName: [
      {required: true, message: '任务名称不能为空', trigger: ['blur', 'change']},
    ],
    jobGroup: [
      {required: true, message: '任务分组不能为空', trigger: ['blur', 'change']},
    ],
    invokeTarget: [
      {required: true, message: '调用目标字符串不能为空', trigger: ['blur', 'change']},
    ],
    cronExpression: [
      {required: true, message: 'cron表达式不能为空', trigger: ['blur', 'change']},
      {validator: this.validateCronExpressionIsValid, trigger: 'blur'}
    ]
  };

  columns: any = [
    {label: 'ID', prop: 'id', sortable: 'custom', width: 50},
    {label: '任务名称', prop: 'jobName', sortable: 'custom', width: 150, showOverflowTooltip: true},
    {
      label: '任务分组', prop: 'jobGroup', sortable: 'custom', render: (createElement, row) => {
        if (row && row.row && row.row.jobGroup === 'DEFAULT') {
          return createElement('el-tag', {
              attrs: {
                type: 'success'
              }
            }, ['默认']
          );
        } else if (row && row.row && row.row.jobGroup === 'SYSTEM') {
          return createElement('el-tag', {
            attrs: {
                type: 'warning'
              }
            }, ['系统']
          );
        } else {
          return createElement('el-tag', {
              attrs: {
                type: 'danger'
              }
            }, ['未知']
          );
        }
      }
    },
    {label: '调用目标字符串', prop: 'invokeTarget', sortable: 'custom', width: 160, showOverflowTooltip: true},
    {label: '执行表达式', prop: 'cronExpression', sortable: 'custom', width: 150, showOverflowTooltip: true},
    {
      label: '任务状态', prop: 'status', sortable: 'custom', render: (createElement, row) => {
        if (row && row.row && row.row.status === '0') {
          return createElement('el-tag', {
              attrs: {
                type: 'success'
              }
            }, ['正常']
          );
        } else if (row && row.row && row.row.status === '1') {
          return createElement('el-tag', {
              attrs: {
                type: 'warning'
              }
            }, ['停止']
          );
        } else {
          return createElement('el-tag', {
              attrs: {
                type: 'danger'
              }
            }, ['未知']
          );
        }
      }
    },
    {label: '创建时间', prop: 'createTime', sortable: 'custom', width: 160, showOverflowTooltip: true},
  ];

  /*table 的参数*/
  options: any = {
    stripe: true, // 是否为斑马纹 table
    loading: false, // 是否添加表格loading加载动画
    highlightCurrentRow: true, // 是否支持当前行高亮显示
    multipleSelect: true, // 是否支持列表项选中功能
  };


  /*操作栏*/
  operates: any = {
    width: 'auto',
    fixed: 'right',
    list: [
      {
        label: '编辑',
        type: 'warning',
        icon: 'el-icon-edit',
        plain: true,
        disabled: () => {
          return false;
        },
        permission: 'monitor:job:edit',
        method: (index, row) => {
          this.handleEdit(index, row);
        }
      },
      {
        label: '删除',
        type: 'danger',
        icon: 'el-icon-delete',
        plain: true,
        disabled: () => {
          return false;
        },
        permission: 'monitor:job:remove',
        method: (index, row) => {
          this.handleDelete(index, row);
        }
      },
      {
        label: '执行一次',
        type: 'success',
        icon: 'el-icon-video-play',
        plain: true,
        disabled: () => {
          return false;
        },
        permission: 'monitor:job:changeStatus',
        method: (index, row) => {
          this.handleExec(index, row);
        }
      },
      {
        label: '详细',
        type: 'info',
        icon: 'el-icon-info',
        plain: true,
        disabled: () => {
          return false;
        },
        permission: 'monitor:job:detail',
        method: (index, row) => {
          this.handleLog(index, row);
        }
      }
    ]
  };

  /*校验cron表达式是否有效*/
  validateCronExpressionIsValid(rule: any, value: any, callback: any) {
    checkCronExpressionIsValid({
      cronExpression: value
    }).then((res: any) => {
      if (res.data && res.data === true) {
        callback();
      } else {
        callback(new Error('cron表达式不合法'));
      }
    }).catch((err: any) => {
      console.error(err);
      callback(new Error('cron表达式不合法'));
    })
  }

  /*新增*/
  handleAdd() {
    this.dialog.title = '新增调度任务';
    this.dialog.isEdit = false;
    this.dialog.dialogFormVisible = true;
    this.dialog.logVisible = false;
  }

  /*编辑*/
  handleEdit(index: number, row: any) {
    this.jobModel = Object.assign({}, row || this.dialog.formData[0]);
    this.dialog.title = '编辑调度任务';
    this.dialog.isEdit = true;
    this.dialog.dialogFormVisible = true;
    this.dialog.logVisible = false;
  }

  /*批量删除*/
  handleBatchDelete() {
    //删除
    this.$confirm('确定要删除选定调度任务吗？', '警告', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }).then(() => {
      const ids: Array<any> = [];
      this.dialog.formData.forEach((item, index) => {
        ids[index] = item.id;
      });
      return removeJob({'ids': ids});
    }).then((response: any) => {
      this.dataTable.refresh();
      this.$message.success(response.msg);
    }).catch((e) => {
      console.error(e);
    });
  }

  /*任务日志*/
  handleJobLogsInfo() {
    this.$router.push('/monitor/job/log').catch((e) => {
      console.error(e);
    });
  }

  /*删除*/
  handleDelete(index: number, row: any) {
    this.$confirm('确定要删除该调度任务吗？', '警告', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }).then(() => {
      return removeJob({'ids': [row.id]});
    }).then((response: any) => {
      this.dataTable.refresh();
      this.$message.success(response.msg);
    }).catch((e) => {
      console.error(e);
    });
  }

  /*调用执行一次*/
  handleExec(index: number, row: any) {
    this.$confirm('确定要立即执行一次吗？', '警告', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }).then(() => {
      return runJob({'id': row.id, 'jobGroup': row.jobGroup});
    }).then((response: any) => {
      this.dataTable.refresh();
      this.$message.success(response.msg);
    }).catch((e) => {
      console.error(e);
    });
  }

  /*任务详情*/
  handleLog(index: number, row: any) {
    this.dialog.logVisible = true;
    this.dialog.dialogVisible = false;
    this.dialog.row = row;
    this.dialog.title = '任务详细';
  }

  /*导出excel*/
  handleExport(): void {
    this.$confirm('确定要导出当前查询的所有调度任务信息吗？', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'info'
    }).then(() => {
      this.selectFormModel.pageNum = null;
      this.selectFormModel.pageSize = null;
      this.selectFormModel.orderByColumn = 'id';
      this.selectFormModel.isAsc = 'asc';

      return exportJob(this.selectFormModel);
    }).then((response: any) => {
      if (response && response.data) {
        (this as any).$download(response.data.fileName);
      }
    }).catch((e) => {
      console.error(e);
    });
  }

  submitForm(): void {
    this.jobForm.validate((valid: boolean) => {
      if (valid) {
        if (this.dialog.isEdit) {
          //编辑
          updateJob(this.jobModel).then((response: any) => {
            this.dataTable.refresh();
            this.reset();
            this.dialog.dialogFormVisible = false;
            this.$message.success(response.msg);
          }).catch((e) => {
            console.error(e);
            validateForm(e.data, this.jobForm, this.jobFormRules);
          });
        } else {
          //新增
          addJob(this.jobModel).then((response: any) => {
            this.dataTable.refresh();
            this.reset();
            this.dialog.dialogFormVisible = false;
            this.$message.success(response.msg);
          }).catch((e) => {
            console.error(e);
            validateForm(e.data, this.jobForm, this.jobFormRules);
          });
        }
      }
    });
  }


  /*搜索*/
  onSearch(): void {
    this.dataTable.refresh();
  }

  /*重置*/
  onRefreshSelectForm(): void {
    //恢复搜索默认信息
    this.selectForm.resetFields();
    this.onSearch();
  }


  /*选中事件*/
  handleSelectionChange(val): void {
    if (val) {
      this.dialog.isBatchRemoveDisabled = val.length <= 0;
      this.dialog.isBatchEditDisabled = val.length !== 1;
    }
    this.dialog.formData = val;
  }

  /*重置表单*/
  reset(): void {
    this.jobModel = {
      jobName: '',
      jobGroup: 'DEFAULT',
      invokeTarget: '',
      cronExpression: '',
      misfirePolicy: '1',
      concurrent: '1',
      status: '1',
      remark: ''
    };
    (this as any).resetForm('jobForm');
  }

  /*关闭对话框*/
  closeDialog() {
    this.$nextTick(() => {
      this.reset();
    });
  }
}
</script>

<style scoped lang="scss">
.tableRow {
  .table {
    margin-top: 10px;
  }

  .el-dialog__body {
    .item {
      margin-bottom: 18px;
    }
  }
}
</style>

